home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 21 / AACD 21.iso / AACD / Utilities / Ghostscript / src / gdevbj10.c < prev    next >
Encoding:
C/C++ Source or Header  |  2001-01-01  |  13.8 KB  |  413 lines

  1. /* Copyright (C) 1990, 1995, 1997, 2000 Aladdin Enterprises.  All rights reserved.
  2.   
  3.   This file is part of AFPL Ghostscript.
  4.   
  5.   AFPL Ghostscript is distributed with NO WARRANTY OF ANY KIND.  No author or
  6.   distributor accepts any responsibility for the consequences of using it, or
  7.   for whether it serves any particular purpose or works at all, unless he or
  8.   she says so in writing.  Refer to the Aladdin Free Public License (the
  9.   "License") for full details.
  10.   
  11.   Every copy of AFPL Ghostscript must include a copy of the License, normally
  12.   in a plain ASCII text file named PUBLIC.  The License grants you the right
  13.   to copy, modify and redistribute AFPL Ghostscript, but only under certain
  14.   conditions described in the License.  Among other things, the License
  15.   requires that the copyright notice and this notice be preserved on all
  16.   copies.
  17. */
  18.  
  19. /*$Id: gdevbj10.c,v 1.3 2000/09/19 19:00:11 lpd Exp $*/
  20. /* Canon Bubble Jet BJ-10e, BJ200, and BJ300 printer driver */
  21. #include "gdevprn.h"
  22.  
  23. /*
  24.  * The following is taken from the BJ200 Programmer's manual.  The top
  25.  * margin is 3mm (0.12"), and the bottom margin is 6.4mm (0.25").  The
  26.  * left and right margin depend on the type of paper -- US letter or
  27.  * A4 -- but ultimately rest on a print width of 203.2mm (8").  For letter
  28.  * paper, the left margin (and hence the right) is 6.4mm (0.25"), while
  29.  * for A4 paper, both are 3.4mm (0.13").
  30.  *
  31.  * The bottom margin requires a bit of care.  The image is printed
  32.  * as strips, each about 3.4mm wide.  We can only attain the bottom 
  33.  * margin if the final strip coincides with it.  Note that each strip
  34.  * is generated using only 48 of the available 64 jets, and the absence
  35.  * of those bottom 16 jets makes our bottom margin, in effect, about
  36.  * 1.1mm (0.04") larger.
  37.  *
  38.  * The bj200 behaves, in effect, as though the origin were at the first
  39.  * printable position, rather than the top left corner of the page, so
  40.  * we add a translation to the initial matrix to compensate for this.
  41.  *
  42.  * Except for the details of getting the margins correct, the bj200 is
  43.  * no different from the bj10e, and uses the same routine to print each
  44.  * page.
  45.  *
  46.  * NOTE:  The bj200 has a DIP switch called "Text scale mode" and if
  47.  * set, it allows the printer to get 66 lines on a letter-sized page
  48.  * by reducing the line spacing by a factor of 14/15.  If this DIP
  49.  * switch is set, the page image printed by ghostscript will also be
  50.  * similarly squeezed.  Thus text scale mode is something ghostscript
  51.  * would like to disable.
  52.  *
  53.  * According to the bj200 manual, which describes the bj10 commands,
  54.  * the printer can be reset either to the settings determined by the
  55.  * DIP switches, or to the factory defaults, and then some of those
  56.  * settings can be specifically overriden.  Unfortunately, the text
  57.  * scale mode and horizontal print position (for letter vs A4 paper)
  58.  * can not be overriden.  On my bj200, the factory settings are for
  59.  * no text scaling and letter paper, thus using the factory defaults
  60.  * also implies letter paper.  I don't know if this is necessarily
  61.  * true for bj200's sold elsewhere, or for other printers that use
  62.  * the same command set.
  63.  *
  64.  * If your factory defaults are in fact the same, you can compile
  65.  * the driver with USE_FACTORY_DEFAULTS defined, in which case the
  66.  * printer will be reset to the factory defaults for letter paper,
  67.  * and reset to the DIP switch settings for A4 paper.  In this case,
  68.  * with letter-sized paper, the text scale mode will be disabled.
  69.  * Further, by leaving the horizontal print position DIP switch set
  70.  * for A4 paper, gs will be able to print on either A4 or letter
  71.  * paper without changing the DIP switch.  Since it's not clear that
  72.  * the factory defaults are universal, the default behaviour is not
  73.  * to define USE_FACTORY_DEFAULTS, and the printer will always be
  74.  * reset to the DIP switch defaults.
  75.  */
  76.  
  77. /*
  78.  * According to md@duesti.fido.de (Matthias Duesterhoeft):
  79.  
  80. It is possible to use the printer Canon BJ-300 (and 330) with Ghostscript if
  81. you use the driver for the Canon BJ-200. The Printer has to be set to
  82. Proprinter Mode. Although it is possible to set the print quality with a DIP
  83. switch, you should add the following to the already existing init-string:
  84. 1B 5B 64 01 00 80  (all numbers in hex)
  85. This sets the print quality to letter quality.
  86.  
  87. The minimum margins are the following:
  88.  
  89. Portrait:
  90. B5/A4: min. left and right margin: 3.4 mm (0.13")
  91. Letter: min. left and right margin: 6.4 mm (0.25")
  92.  
  93. Landscape:
  94. B4: min. left and right margin: 9.3 mm (0.37")
  95. A3: min. left and right margin: 37.3 mm (1.47")
  96.  
  97. The recommended top margin is 12.7 mm (0.5"), although the printer is capable
  98. to start at 0 mm. The recommended bottom margin is 25.4 mm (1"), but 12.7 mm
  99. (0.5") are possible, too. If you ask me, don't use the recommended top and
  100. bottom margins, use 0" and 0.5".
  101.  
  102.  */
  103.  
  104. #define BJ200_TOP_MARGIN        0.12
  105. #define BJ200_BOTTOM_MARGIN        0.29
  106. #define BJ200_LETTER_SIDE_MARGIN    0.25
  107. #define BJ200_A4_SIDE_MARGIN        0.13
  108.  
  109. private dev_proc_open_device(bj200_open);
  110.  
  111. private dev_proc_print_page(bj10e_print_page);
  112.  
  113. private gx_device_procs prn_bj200_procs =
  114.   prn_procs(bj200_open, gdev_prn_output_page, gdev_prn_close);
  115.  
  116. gx_device_printer far_data gs_bj200_device =
  117.   prn_device(prn_bj200_procs, "bj200",
  118.     DEFAULT_WIDTH_10THS,
  119.     DEFAULT_HEIGHT_10THS,
  120.     360,                /* x_dpi */
  121.     360,                /* y_dpi */
  122.     0, 0, 0, 0,            /* margins filled in by bj200_open */
  123.     1, bj10e_print_page);
  124.  
  125. /*
  126.  * (<simon@pogner.demon.co.uk>, aka <sjwright@cix.compulink.co.uk>):
  127.  * My bj10ex, which as far as I can tell is just like a bj10e, works
  128.  * fine with the bj200 setup here.
  129.  */
  130.  
  131. gx_device_printer far_data gs_bj10e_device =
  132.   prn_device(prn_bj200_procs, "bj10e",
  133.     DEFAULT_WIDTH_10THS,
  134.     DEFAULT_HEIGHT_10THS,
  135.     360,                /* x_dpi */
  136.     360,                /* y_dpi */
  137.     0,0,0,0,            /* margins */
  138.     1, bj10e_print_page);
  139.  
  140. /*
  141.  * Notes on the BJ10e/BJ200 command set.
  142.  *
  143.  
  144. According to the BJ200 manual, the "set initial condition" sequence (ESC [
  145. K) has 2 bytes which can override the DIP switches -- these are the last 2
  146. bytes.  Several bits are listed as "reserved" -- one or more may possibly
  147. affect the sheet feeder.  The first is referred to as <P1>, with the
  148. following meaning:
  149.                 1        0
  150. bit 7    ignore/process P1    ignore        process
  151. bit 6    reserved
  152. bit 5    alarm            disabled    enabled
  153. bit 4    automatic CR        CR+LF        CR
  154. bit 3    automatic LF        CR+LF        LF
  155. bit 2    page length        12 inches    11 inches
  156. bit 1    style for zero        slashed        not slashed
  157. bit 0    character set        set 2        set 1
  158.  
  159. The last byte is <P2>, with the following meaning:
  160.                 1        0
  161. bit 7    ignore/process P2    ignore        process
  162. bit 6    code page        850        437
  163. bit 5    reserved
  164. bit 4    reserved
  165. bit 3    reserved
  166. bit 2    reserved
  167. bit 1    reserved
  168. bit 0    reserved
  169.  
  170. The automatic CR setting is important to gs, but the rest shouldn't matter
  171. (gs doesn't print characters or send LF, and it explicitly sets the page
  172. length).  The sequence ESC 5 <n> controls automatic CR -- if <n> is 0x00,
  173. it is turned off (CR only) and if <n> is 0x01, it is turned on (CR + LF).
  174. So we do following: Change the initialization string to so that the last 2
  175. of the 9 bytes are \200 rather than \000.  Then add
  176.     |* Turn off automatic carriage return, otherwise we get line feeds. *|
  177.     fwrite("\0335\000", 1, 3, prn_stream);
  178. after the initialization.  (Actually, instead of setting the last 2 bytes
  179. to \200, we suppress them altogether by changing the byte count from \004
  180. to \002 (the byte count is the 4th (low 8 bits) and 5th (high 8 bits) bytes
  181. in the initialization sequence).)
  182.  
  183. */
  184.  
  185. /* ------ Internal routines ------ */
  186.  
  187. /* Open the printer, and set the margins. */
  188. private int
  189. bj200_open(gx_device *pdev)
  190. {
  191.     /* Change the margins according to the paper size.
  192.        The top and bottom margins don't seem to depend on the
  193.        page length, but on the paper handling mechanism;
  194.        The side margins do depend on the paper width, as the
  195.        printer centres the 8" print line on the page. */
  196.  
  197.     static const float a4_margins[4] =
  198.      {    BJ200_A4_SIDE_MARGIN, BJ200_BOTTOM_MARGIN,
  199.         BJ200_A4_SIDE_MARGIN, BJ200_TOP_MARGIN
  200.      };
  201.     static const float letter_margins[4] =
  202.      {    BJ200_LETTER_SIDE_MARGIN, BJ200_BOTTOM_MARGIN,
  203.         BJ200_LETTER_SIDE_MARGIN, BJ200_TOP_MARGIN
  204.      };
  205.  
  206.     gx_device_set_margins(pdev,
  207.         (pdev->width / pdev->x_pixels_per_inch <= 8.4 ?
  208.          a4_margins : letter_margins),
  209.         true);
  210.     return gdev_prn_open(pdev);
  211. }
  212.  
  213. /* Send the page to the printer. */
  214. private int
  215. bj10e_print_page(gx_device_printer *pdev, FILE *prn_stream)
  216. {    int line_size = gx_device_raster((gx_device *)pdev, 0);
  217.     int xres = pdev->x_pixels_per_inch;
  218.     int yres = pdev->y_pixels_per_inch;
  219.     int mode = (yres == 180 ?
  220.             (xres == 180 ? 11 : 12) :
  221.             (xres == 180 ? 14 : 16));
  222.     int bytes_per_column = (yres == 180) ? 3 : 6;
  223.     int bits_per_column = bytes_per_column * 8;
  224.     int skip_unit = bytes_per_column * 3;
  225.     byte *in = (byte *)gs_malloc(8, line_size, "bj10e_print_page(in)");
  226.     byte *out = (byte *)gs_malloc(bits_per_column, line_size, "bj10e_print_page(out)");
  227.     int lnum = 0;
  228.     int skip = 0;
  229.     int code = 0;
  230.     int last_row = dev_print_scan_lines(pdev);
  231.     int limit = last_row - bits_per_column;
  232.  
  233.     if ( in == 0 || out == 0 )
  234.     {    code = gs_note_error(gs_error_VMerror);
  235.         goto fin;
  236.     }
  237.  
  238.     /* Initialize the printer. */
  239. #ifdef USE_FACTORY_DEFAULTS
  240.     /* Check for U.S. letter vs. A4 paper. */
  241.     fwrite(( pdev->width / pdev->x_pixels_per_inch <= 8.4 ?
  242.         "\033[K\002\000\000\044"    /*A4--DIP switch defaults*/ :
  243.         "\033[K\002\000\004\044"    /*letter--factory defaults*/ ),
  244.            1, 7, prn_stream);
  245. #else
  246.     fwrite("\033[K\002\000\000\044", 1, 7, prn_stream);
  247. #endif
  248.  
  249.     /* Turn off automatic carriage return, otherwise we get line feeds. */
  250.     fwrite("\0335\000", 1, 3, prn_stream);
  251.  
  252.     /* Set vertical spacing. */
  253.     fwrite("\033[\\\004\000\000\000", 1, 7, prn_stream);
  254.     fputc(yres & 0xff, prn_stream);
  255.     fputc(yres >> 8, prn_stream);
  256.  
  257.     /* Set the page length.  This is the printable length, in inches. */
  258.     fwrite("\033C\000", 1, 3, prn_stream);
  259.     fputc((last_row + yres - 1)/yres, prn_stream);
  260.  
  261.     /* Transfer pixels to printer.  The last row we can print is defined
  262.        by "last_row".  Only the bottom of the print head can print at the
  263.        bottom margin, and so we align the final printing pass.  The print
  264.        head is kept from moving below "limit", which is exactly one pass
  265.        above the bottom margin.  Once it reaches this limit, we make our
  266.        final printing pass of a full "bits_per_column" rows. */
  267.     while ( lnum < last_row )
  268.        {    
  269.         byte *in_data;
  270.         byte *in_end = in + line_size;
  271.         byte *out_beg = out;
  272.         byte *out_end = out + bytes_per_column * pdev->width;
  273.         byte *outl = out;
  274.         int bnum;
  275.  
  276.         /* Copy 1 scan line and test for all zero. */
  277.         code = gdev_prn_get_bits(pdev, lnum, in, &in_data);
  278.         if ( code < 0 ) goto xit;
  279.         /* The mem... or str... functions should be faster than */
  280.         /* the following code, but all systems seem to implement */
  281.         /* them so badly that this code is faster. */
  282.            {    register const long *zip = (const long *)in_data;
  283.             register int zcnt = line_size;
  284.             register const byte *zipb;
  285.             for ( ; zcnt >= 4 * sizeof(long); zip += 4, zcnt -= 4 * sizeof(long) )
  286.                {    if ( zip[0] | zip[1] | zip[2] | zip[3] )
  287.                     goto notz;
  288.                }
  289.             zipb = (const byte *)zip;
  290.             while ( --zcnt >= 0 )
  291.                {
  292.                 if ( *zipb++ )
  293.                     goto notz;
  294.                }
  295.             /* Line is all zero, skip */
  296.             lnum++;
  297.             skip++;
  298.             continue;
  299. notz:            ;
  300.            }
  301.  
  302.         /* Vertical tab to the appropriate position.  Note here that
  303.            we make sure we don't move below limit. */
  304.         if ( lnum > limit )
  305.             {    skip -= (lnum - limit);
  306.             lnum = limit;
  307.             }
  308.         while ( skip > 255 )
  309.            {    fputs("\033J\377", prn_stream);
  310.             skip -= 255;
  311.            }
  312.         if ( skip )
  313.             fprintf(prn_stream, "\033J%c", skip);
  314.  
  315.         /* If we've printed as far as "limit", then reset "limit"
  316.            to "last_row" for the final printing pass. */
  317.         if ( lnum == limit )
  318.             limit = last_row;
  319.         skip = 0;
  320.  
  321.         /* Transpose in blocks of 8 scan lines. */
  322.         for ( bnum = 0; bnum < bits_per_column; bnum += 8 )
  323.            {    int lcnt = min(8, limit - lnum);
  324.             byte *inp = in;
  325.             byte *outp = outl;
  326.                lcnt = gdev_prn_copy_scan_lines(pdev,
  327.                 lnum, in, lcnt * line_size);
  328.             if ( lcnt < 0 )
  329.                {    code = lcnt;
  330.                 goto xit;
  331.                }
  332.             if ( lcnt < 8 )
  333.                 memset(in + lcnt * line_size, 0,
  334.                        (8 - lcnt) * line_size);
  335.             for ( ; inp < in_end; inp++, outp += bits_per_column )
  336.                {    gdev_prn_transpose_8x8(inp, line_size,
  337.                     outp, bytes_per_column);
  338.                }
  339.             outl++;
  340.             lnum += lcnt;
  341.             skip += lcnt;
  342.            }
  343.  
  344.         /* Send the bits to the printer.  We alternate horizontal
  345.            skips with the data.  The horizontal skips are in units
  346.            of 1/120 inches, so we look at the data in groups of
  347.            3 columns, since 3/360 = 1/120, and 3/180 = 2/120.  */
  348.         outl = out;
  349.         do
  350.            {    int count;
  351.             int n;
  352.             byte *out_ptr;
  353.  
  354.             /* First look for blank groups of columns. */
  355.             while(outl < out_end)
  356.                {    n = count = min(out_end - outl, skip_unit);
  357.                 out_ptr = outl;
  358.                 while ( --count >= 0 )
  359.                    {    if ( *out_ptr++ )
  360.                         break;
  361.                    }
  362.                 if ( count >= 0 )
  363.                     break;
  364.                 else
  365.                     outl = out_ptr;
  366.                }
  367.             if (outl >= out_end)
  368.                 break;
  369.             if (outl > out_beg)
  370.                {    count = (outl - out_beg) / skip_unit;
  371.                 if ( xres == 180 ) count <<= 1;
  372.                 fprintf(prn_stream, "\033d%c%c",
  373.                     count & 0xff, count >> 8);
  374.                }
  375.  
  376.             /* Next look for non-blank groups of columns. */
  377.             out_beg = outl;
  378.             outl += n;
  379.             while(outl < out_end)
  380.                {    n = count = min(out_end - outl, skip_unit);
  381.                 out_ptr = outl;
  382.                 while ( --count >= 0 )
  383.                    {    if ( *out_ptr++ )
  384.                         break;
  385.                    }
  386.                 if ( count < 0 )
  387.                     break;
  388.                 else
  389.                     outl += n;
  390.                }
  391.             count = outl - out_beg + 1;
  392.             fprintf(prn_stream, "\033[g%c%c%c",
  393.                 count & 0xff, count >> 8, mode);
  394.             fwrite(out_beg, 1, count - 1, prn_stream);
  395.             out_beg = outl;
  396.             outl += n;
  397.            }
  398.         while ( out_beg < out_end );
  399.  
  400.         fputc('\r', prn_stream);
  401.        }
  402.  
  403.     /* Eject the page */
  404. xit:    fputc(014, prn_stream);    /* form feed */
  405.     fflush(prn_stream);
  406. fin:    if ( out != 0 )
  407.         gs_free((char *)out, bits_per_column, line_size,
  408.             "bj10e_print_page(out)");
  409.     if ( in != 0 )
  410.         gs_free((char *)in, 8, line_size, "bj10e_print_page(in)");
  411.     return code;
  412. }
  413.